Skip to content

Fix duplicate client/operation names when operation IDs contain multiple underscores#5348

Merged
lahma merged 2 commits intomasterfrom
copilot/fix-duplicate-classes-issue
Mar 6, 2026
Merged

Fix duplicate client/operation names when operation IDs contain multiple underscores#5348
lahma merged 2 commits intomasterfrom
copilot/fix-duplicate-classes-issue

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

MultipleClientsFromOperationIdOperationNameGenerator used the second-to-last underscore segment as client name and last segment as operation name. Any two operation IDs sharing the same suffix (e.g. Orders_items_get and Products_items_get) mapped to the same (client="items", operation="get") pair, producing duplicate generated classes and methods.

Changes

  • GetClientName: switched from second-to-last segment to everything before the first _
  • GetOperationName: switched from LastIndexOf('_') to IndexOf('_') — returns everything after the first _
Operation ID Old client → operation New client → operation
OperationId_Test OperationIdTest OperationIdTest
Orders_items_get itemsget Ordersitems_get
Products_items_get itemsget ⚠️ duplicate Productsitems_get

Since OpenAPI mandates globally unique operation IDs, splitting at the first _ guarantees that no two operation IDs can ever produce the same (client, operation) pair. The fix also propagates to MultipleClientsFromFirstTagAndOperationNameGenerator, which inherits GetOperationName from the base class.

Tests

  • Updated existing test expectations to match the new behavior
  • Added explicit operation-name tests for MultipleClientsFromOperationId
  • Added regression tests asserting that distinct operation IDs always yield distinct (client, operation) pairs
Original prompt

This section details on the original issue you should resolve

<issue_title>Underscores - the source of all evil when used, but should work out of the box.</issue_title>
<issue_description>We have a customer openapi.json which we query at runtime to generate our bindings.
In our case we are getting duplicate classes, due to the standard implementation using the underscore as separator, and only giving back the last chunk, which is obviously bad.

Example: https://github.com/RicoSuter/NSwag/blob/master/src/NSwag.CodeGeneration/OperationNameGenerators/MultipleClientsFromOperationIdOperationNameGenerator.cs#L108

This also applies to
#4178 #3450 #1749 #596

Neither we, nor the customer can change those definition file. Manually iterating the definition for replacement is also a huge pain, as we never know where stuff is referenced. And even if we manage to find all references, we cannot rely on removing the underscore, as this might actually generate duplicate identifiers.

  • Having an underscore in an OperationId should work.
  • Having an underscore in a schema name should also work.

I would suggest using "/" as separator char, as it is invalid anyway, but an "_" underscore is very likely to occur.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

…iple underscores

Use the first underscore as the separator in MultipleClientsFromOperationIdOperationNameGenerator:
- GetClientName: everything before the first '_' = client name
- GetOperationName: everything after the first '_' = operation name

This guarantees uniqueness since OpenAPI requires globally unique operation IDs.
Previously, 'Orders_items_get' and 'Products_items_get' both produced
client='items', operation='get', causing duplicate generated code.

Co-authored-by: lahma <171892+lahma@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix duplicate class generation due to underscore usage Fix duplicate client/operation names when operation IDs contain multiple underscores Mar 6, 2026
Copilot finished work on behalf of lahma March 6, 2026 10:25
@lahma lahma requested a review from Copilot March 6, 2026 20:54
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a long-standing bug in MultipleClientsFromOperationIdOperationNameGenerator where operation IDs with multiple underscores (e.g., Orders_items_get and Products_items_get) would map to duplicate (client, operation) pairs, causing duplicate generated classes and methods. The fix simplifies the splitting strategy to always use the first underscore as the delimiter — everything before it becomes the client name, everything after becomes the operation name. Since OpenAPI mandates globally unique operation IDs, this guarantees uniqueness of (client, operation) pairs.

Changes:

  • GetClientName: Returns everything before the first underscore (instead of the second-to-last segment)
  • GetOperationName: Returns everything after the first underscore (instead of the last segment)
  • Test updates and additions to cover the new behavior and regression-test uniqueness guarantees

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/NSwag.CodeGeneration/OperationNameGenerators/MultipleClientsFromOperationIdOperationNameGenerator.cs Simplified GetClientName and GetOperationName to split on the first underscore instead of the last
src/NSwag.CodeGeneration.Tests/CodeGenerationTests.cs Updated existing test expectations to match new behavior, added operation-name tests for MultipleClientsFromOperationId, and added regression tests asserting uniqueness of (client, operation) pairs

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@lahma lahma marked this pull request as ready for review March 6, 2026 21:00
@lahma lahma merged commit eac9c1f into master Mar 6, 2026
7 checks passed
@lahma lahma deleted the copilot/fix-duplicate-classes-issue branch March 6, 2026 21:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Underscores - the source of all evil when used, but should work out of the box.

3 participants